package com.vito.framework.base.exception;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.vito.support.ApiResponse;
import com.vito.support.ResultEnum;

@RestControllerAdvice
public class GlobalExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 处理请求对象属性不满足校验规则的异常信息
     *
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ApiResponse exception(HttpServletRequest request, MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        final List<FieldError> fieldErrors = result.getFieldErrors();
        StringBuilder builder = new StringBuilder();

        for (FieldError error : fieldErrors) {
            builder.append(error.getDefaultMessage()).append("\n");
        }
        logger.error(builder.toString());
        return ApiResponse.of(ResultEnum.PARAMS_INVALID);
    }

//    /**
//     * 处理请求对象属性不满足校验规则的异常信息
//     *
//     * @param request
//     * @param exception
//     * @return
//     * @throws Exception
//     */
//    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
//    public ApiResponse exception(HttpServletRequest request, MethodArgumentTypeMismatchException exception) {
//        MethodParameter result = exception.getParameter();
//        String parameterName = result.getParameterName();
//
//        return ApiResponse.of(ResultEnum.PARAMS_INVALID).withMessage("无法解析的" + parameterName);
//    }

    /**
     * 处理请求单个参数不满足校验规则的异常信息
     *
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public ApiResponse constraintViolationExceptionHandler(HttpServletRequest request, HttpRequestMethodNotSupportedException exception) {
        logger.error(exception.getMessage());
        return ApiResponse.of(ResultEnum.METHOD_INVALID);
    }

    /**
     * 处理请求单个参数不满足校验规则的异常信息
     *
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ApiResponse constraintViolationExceptionHandler(HttpServletRequest request, ConstraintViolationException exception) {
        logger.error(exception.getMessage());
        return ApiResponse.of(ResultEnum.PARAMS_INVALID);
    }

    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public ApiResponse constraintViolationExceptionHandler(HttpServletRequest request, HttpMessageNotReadableException exception) {
        logger.error(exception.getMessage());
        return ApiResponse.of(ResultEnum.PARAMS_INVALID);
    }

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ApiResponse constraintViolationExceptionHandler(HttpServletRequest request, MissingServletRequestParameterException exception) {
        logger.error(exception.getMessage());
        return ApiResponse.of(ResultEnum.PARAMS_INVALID);
    }

    /**
     * 处理未定义的其他异常信息
     *
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ApiResponse exceptionHandler(HttpServletRequest request, Exception exception) {
        logger.error(exception.getMessage(), exception);
        return ApiResponse.of(ResultEnum.FAIL);
    }
}
